#include "gameboard.h"

GameBoard::GameBoard(QWidget *parent)
    : QWidget(parent), isBlackTurn(true), gameOverFlag(false)
{
    // 初始化棋盘数组
    for (int i = 0; i < BOARD_SIZE; ++i) {
        for (int j = 0; j < BOARD_SIZE; ++j) {
            board[i][j] = EMPTY;
        }
    }

    setFixedSize(BOARD_SIZE * CELL_SIZE + 2 * BOARD_MARGIN,
                 BOARD_SIZE * CELL_SIZE + 2 * BOARD_MARGIN);
    setWindowTitle("五子棋游戏");
}

void GameBoard::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿

    // 绘制棋盘
    drawBoard(painter);

    // 绘制棋子
    drawStones(painter);
}

void GameBoard::drawBoard(QPainter &painter)
{
    painter.setPen(QPen(Qt::black, 1));

    // 绘制横向线条
    for (int i = 0; i < BOARD_SIZE; ++i) {
        int y = BOARD_MARGIN + i * CELL_SIZE;
        painter.drawLine(BOARD_MARGIN, y,
                         BOARD_MARGIN + (BOARD_SIZE - 1) * CELL_SIZE, y);
    }

    // 绘制纵向线条
    for (int j = 0; j < BOARD_SIZE; ++j) {
        int x = BOARD_MARGIN + j * CELL_SIZE;
        painter.drawLine(x, BOARD_MARGIN,
                         x, BOARD_MARGIN + (BOARD_SIZE - 1) * CELL_SIZE);
    }

    // 绘制天元和星位（五子棋中常用的标记点）
    int center = (BOARD_SIZE - 1) / 2;
    int starPoints[] = {3, center, BOARD_SIZE - 4};

    painter.setBrush(Qt::black);
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            int x = BOARD_MARGIN + starPoints[i] * CELL_SIZE;
            int y = BOARD_MARGIN + starPoints[j] * CELL_SIZE;
            painter.drawEllipse(x - 3, y - 3, 6, 6);
        }
    }
}

void GameBoard::drawStones(QPainter &painter)
{
    for (int i = 0; i < BOARD_SIZE; ++i) {
        for (int j = 0; j < BOARD_SIZE; ++j) {
            if (board[i][j] != EMPTY) {
                int x = BOARD_MARGIN + j * CELL_SIZE;
                int y = BOARD_MARGIN + i * CELL_SIZE;

                // 设置棋子颜色
                if (board[i][j] == BLACK) {
                    painter.setBrush(Qt::black);
                } else {
                    painter.setBrush(Qt::white);
                }

                // 绘制棋子
                painter.setPen(QPen(Qt::black, 1));
                painter.drawEllipse(x - CELL_SIZE/2 + 2, y - CELL_SIZE/2 + 2,
                                    CELL_SIZE - 4, CELL_SIZE - 4);

                // 如果是当前轮到的颜色，画个标记
                if ((board[i][j] == BLACK && isBlackTurn) ||
                    (board[i][j] == WHITE && !isBlackTurn)) {
                    painter.setPen(QPen(Qt::red, 2));
                    painter.drawEllipse(x - CELL_SIZE/2 + 4, y - CELL_SIZE/2 + 4,
                                        CELL_SIZE - 8, CELL_SIZE - 8);
                }
            }
        }
    }
}

void GameBoard::mousePressEvent(QMouseEvent *event)
{
    if (gameOverFlag) return; // 游戏结束则不响应点击

    // 使用新的 position() 方法获取坐标
    QPoint pos = event->position().toPoint();
    int clickedPoint = getNearestPoint(pos.x(), pos.y());
    if (clickedPoint == -1) return; // 点击位置无效

    int row = clickedPoint / BOARD_SIZE;
    int col = clickedPoint % BOARD_SIZE;

    // 检查该位置是否已有棋子
    if (board[row][col] != EMPTY) {
        return;
    }

    // 放置棋子
    board[row][col] = isBlackTurn ? BLACK : WHITE;

    // 检查是否获胜
    if (checkWin(row, col)) {
        gameOverFlag = true;
        int winner = isBlackTurn ? BLACK : WHITE;
        QString winnerStr = (winner == BLACK) ? "黑棋" : "白棋";
        QMessageBox::information(this, "游戏结束",
                                 QString("恭喜！%1获胜！").arg(winnerStr));
        emit gameOver(winner);
        return;
    }

    // 检查是否平局（棋盘满了）
    bool isFull = true;
    for (int i = 0; i < BOARD_SIZE; ++i) {
        for (int j = 0; j < BOARD_SIZE; ++j) {
            if (board[i][j] == EMPTY) {
                isFull = false;
                break;
            }
        }
        if (!isFull) break;
    }

    if (isFull) {
        QMessageBox::information(this, "游戏结束", "平局！");
        emit gameOver(0); // 0表示平局
        return;
    }

    // 切换玩家
    isBlackTurn = !isBlackTurn;

    update(); // 重绘界面
}

int GameBoard::getNearestPoint(int x, int y)
{
    // 检查是否在棋盘范围内
    if (x < BOARD_MARGIN - CELL_SIZE/2 ||
        x > BOARD_MARGIN + (BOARD_SIZE - 1) * CELL_SIZE + CELL_SIZE/2 ||
        y < BOARD_MARGIN - CELL_SIZE/2 ||
        y > BOARD_MARGIN + (BOARD_SIZE - 1) * CELL_SIZE + CELL_SIZE/2) {
        return -1;
    }

    // 找到最近的交叉点
    int nearestRow = (y - BOARD_MARGIN + CELL_SIZE/2) / CELL_SIZE;
    int nearestCol = (x - BOARD_MARGIN + CELL_SIZE/2) / CELL_SIZE;

    // 检查距离是否在有效范围内
    int centerX = BOARD_MARGIN + nearestCol * CELL_SIZE;
    int centerY = BOARD_MARGIN + nearestRow * CELL_SIZE;

    if (abs(x - centerX) <= CELL_SIZE/2 && abs(y - centerY) <= CELL_SIZE/2) {
        if (nearestRow >= 0 && nearestRow < BOARD_SIZE &&
            nearestCol >= 0 && nearestCol < BOARD_SIZE) {
            return nearestRow * BOARD_SIZE + nearestCol;
        }
    }

    return -1;
}

bool GameBoard::checkWin(int row, int col)
{
    // 检查四个方向：水平、垂直、左上到右下、右上到左下
    int directions[4][2] = {{0, 1}, {1, 0}, {1, 1}, {1, -1}};

    for (int i = 0; i < 4; ++i) {
        if (checkLine(row, col, directions[i][0], directions[i][1])) {
            return true;
        }
    }

    return false;
}

bool GameBoard::checkLine(int row, int col, int dr, int dc)
{
    int color = board[row][col];
    int count = 1; // 当前棋子算一个

    // 向一个方向检查
    int r = row + dr;
    int c = col + dc;
    while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE &&
           board[r][c] == color) {
        count++;
        r += dr;
        c += dc;
    }

    // 向相反方向检查
    r = row - dr;
    c = col - dc;
    while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE &&
           board[r][c] == color) {
        count++;
        r -= dr;
        c -= dc;
    }

    return count >= 5;
}

void GameBoard::resetGame()
{
    // 重置棋盘
    for (int i = 0; i < BOARD_SIZE; ++i) {
        for (int j = 0; j < BOARD_SIZE; ++j) {
            board[i][j] = EMPTY;
        }
    }

    isBlackTurn = true;
    gameOverFlag = false;
    update();
}
